﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using UnityEngine;
using UnityGameFramework.Runtime;

namespace ProjectMG
{
    public static class BinaryReaderExtension
    {
        public static Color32 ReadColor32(this BinaryReader binaryReader)
        {
            return new Color32(binaryReader.ReadByte(), binaryReader.ReadByte(), binaryReader.ReadByte(), binaryReader.ReadByte());
        }

        public static Color ReadColor(this BinaryReader binaryReader)
        {
            return new Color(binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle());
        }

        public static DateTime ReadDateTime(this BinaryReader binaryReader)
        {
            return new DateTime(binaryReader.ReadInt64());
        }

        public static Quaternion ReadQuaternion(this BinaryReader binaryReader)
        {
            return new Quaternion(binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle());
        }

        public static Rect ReadRect(this BinaryReader binaryReader)
        {
            return new Rect(binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle());
        }

        public static Vector2 ReadVector2(this BinaryReader binaryReader)
        {
            return new Vector2(binaryReader.ReadSingle(), binaryReader.ReadSingle());
        }

        public static Vector3 ReadVector3(this BinaryReader binaryReader)
        {
            return new Vector3(binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle());
        }

        public static Vector4 ReadVector4(this BinaryReader binaryReader)
        {
            return new Vector4(binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle(), binaryReader.ReadSingle());
        }

        public static int[] ReadIntArray(this BinaryReader binaryReader)
        {
            byte len = binaryReader.ReadByte();
            int[] arr = new int[len];
            for (int i = 0; i < len; i++)
            {
                arr[i] = binaryReader.Read7BitEncodedInt32();
            }
            return arr;
        }

        public static T[] ParseArray<T>(this BinaryReader binaryReader)
        {
            int length = binaryReader.Read7BitEncodedInt32();
            T[] arr = new T[length];
            for (int i = 0; i < length; i++)
            {
                arr[i] = binaryReader.ParseSystemType<T>();
            }
            return arr;
        }

        public static List<T> ParseList<T>(this BinaryReader binaryReader)
        {
            int length = binaryReader.Read7BitEncodedInt32();
            List<T> list = new List<T>();
            for (int i = 0; i < length; i++)
            {
                list.Add(binaryReader.ParseSystemType<T>());
            }
            return list;
        }

        public static Dictionary<TKey, TValue> ParseDictionary<TKey, TValue>(this BinaryReader binaryReader)
        {
            int length = binaryReader.Read7BitEncodedInt32();
            Dictionary<TKey, TValue> dictionary = new Dictionary<TKey, TValue>();
            for (int i = 0; i < length; i++)
            {
                TKey key = binaryReader.ParseSystemType<TKey>();
                TValue value = binaryReader.ParseSystemType<TValue>();
                dictionary.Add(key, value);
            }
            return dictionary;
        }

        public static T ParseSystemType<T>(this BinaryReader binaryReader)
        {
            Type type = typeof(T);
            if (type == typeof(string))
            {
                return (T)(object)binaryReader.ReadString();
            }
            else if (type == typeof(bool))
            {
                return (T)(object)binaryReader.ReadBoolean();
            }
            else if (type == typeof(byte))
            {
                return (T)(object)binaryReader.ReadByte();
            }
            else if (type == typeof(sbyte))
            {
                return (T)(object)binaryReader.ReadSByte();
            }
            else if (type == typeof(char))
            {
                return (T)(object)binaryReader.ReadChar();
            }
            else if (type == typeof(decimal))
            {
                return (T)(object)binaryReader.ReadDecimal();
            }
            else if (type == typeof(DateTime))
            {
                return (T)(object)binaryReader.ReadDateTime();
            }
            else if (type == typeof(int))
            {
                return (T)(object)binaryReader.Read7BitEncodedInt32();
            }
            else if (type == typeof(short))
            {
                return (T)(object)binaryReader.ReadInt16();
            }
            else if (type == typeof(long))
            {
                return (T)(object)binaryReader.Read7BitEncodedInt64();
            }
            else if (type == typeof(uint))
            {
                return (T)(object)binaryReader.Read7BitEncodedUInt32();
            }
            else if (type == typeof(ushort))
            {
                return (T)(object)binaryReader.ReadUInt16();
            }
            else if (type == typeof(ulong))
            {
                return (T)(object)binaryReader.Read7BitEncodedUInt64();
            }
            else if (type == typeof(float))
            {
                return (T)(object)binaryReader.ReadSingle();
            }
            else if (type == typeof(double))
            {
                return (T)(object)binaryReader.ReadDouble();
            }
            else if(type == typeof(Color))
            {
                return (T)(object)binaryReader.ReadColor();
            }
            else if (type == typeof(Color32))
            {
                return (T)(object)binaryReader.ReadColor32();
            }
            else if (type == typeof(Rect))
            {
                return (T)(object)binaryReader.ReadRect();
            }
            else if (type == typeof(Vector2))
            {
                return (T)(object)binaryReader.ReadVector2();
            }
            else if (type == typeof(Vector3))
            {
                return (T)(object)binaryReader.ReadVector3();
            }
            else if (type == typeof(Vector4))
            {
                return (T)(object)binaryReader.ReadVector4();
            }
            else if (type == typeof(Quaternion))
            {
                return (T)(object)binaryReader.ReadQuaternion();
            }
            else
            {
                Log.Error("data type that does not exist：{0}!", type.ToString());
            }
            return default(T);
        }
    }
}
